package com.google.code.stalkernet.message;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInput;
import java.io.DataInputStream;
import java.io.EOFException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class MessageUnmarshaller
{
    private final ByteArrayOutputStream output =
        new ByteArrayOutputStream ();

    public Message [] unmarshall (byte [] buffer, int offset, int length)
    {
        if (buffer == null)
            throw new IllegalArgumentException ("Buffer is null");

        if (offset < 0)
            throw new IllegalArgumentException ("Offset (" + offset + ")< 0");

        if (length < 0)
            throw new IllegalArgumentException ("Length (" + length + ") < 0");

        int bufferLength = buffer.length;

        if (offset + length > bufferLength)
            throw new IllegalArgumentException (
                "Offset (" + offset + ") + length (" + length +
                ") > buffer length (" + bufferLength + ")");

        output.write (buffer, offset, length);

        ByteArrayInputStream input = new ByteArrayInputStream (
            output.toByteArray ());
        DataInput dataInput = new DataInputStream (input);

        List <Message> messages = new ArrayList <> ();
        try
        {
            while (true)
            {
                input.mark (0);
                messages.add (MessageUtils.unmarshalMessage (dataInput));
            }
        }
        catch (EOFException ex)
        {
            input.reset ();
            output.reset ();

            int available = input.available ();
            if (available > 0)
            {
                byte [] b = new byte [available];
                try
                {
                    if (input.read (b) != available)
                        throw new Error ("Impossible");
                    output.write (b);
                }
                catch (IOException exx)
                {
                    throw new Error ("Impossible", exx);
                }
            }
        }
        catch (IOException ex)
        {
            throw new Error ("Impossible", ex);
        }
        return messages.toArray (new Message [messages.size ()]);
    }
}
